import re
from typing import List, Dict, Any
from sqlalchemy.orm import Session
from .models import ResourceDetails, RelationshipDefinition, ResourceEntitiesMap
from .dependency_analyzer import DependencyAnalyzer

class NLPProcessor:
    def __init__(self, db: Session):
        self.db = db
        self.dependency_analyzer = DependencyAnalyzer(db)
    
    def extract_entities_from_query(self, query: str) -> List[str]:
        """从查询中提取实体名称，增强对上下游依赖关键词的处理"""
        # 获取所有资源名称作为参考
        all_resources = self.get_all_resource_details()
        resource_names = [resource['name'] for resource in all_resources]
        
        # 查找查询中包含的完整资源名称
        matched_entities = []
        for name in resource_names:
            if name in query:
                matched_entities.append(name)
        
        # 特殊处理包含关键词的查询
        if not matched_entities:
            # 处理包含'test'的查询
            if 'test' in query.lower():
                matched_entities.extend([name for name in resource_names if '测试' in name])
            
            # 处理包含'94'的查询
            if '94' in query:
                matched_entities.extend([name for name in resource_names if '94' in name])
            
            # 处理包含'tomcat'的查询
            if 'tomcat' in query.lower():
                matched_entities.extend([name for name in resource_names if 'tomcat' in name.lower()])
        
        # 如果仍然没有找到匹配，使用关键词搜索
        if not matched_entities:
            # 移除常见的停用词和疑问词
            stop_words = ['什么', '如何', '为什么', '哪个', '哪里', '有没有', '是否', '关系', '有', '和', '与', '及', '以及', '或者', '还是', '查找', '搜索', '所有', '包含', '名称', '节点', '资源', '相关', '通过', '连接', '开始', '间接', '关联', '上游', '下游', '依赖', '被', '于']
            
            # 尝试不同的关键词提取方法
            # 方法1: 直接匹配资源名称中的部分字符串
            for name in resource_names:
                # 移除特殊字符进行模糊匹配
                clean_name = re.sub(r'[^\w\u4e00-\u9fff]', '', name)  # 保留中文、英文和数字
                clean_query = re.sub(r'[^\w\u4e00-\u9fff]', '', query)
                if clean_name in clean_query or clean_query in clean_name:
                    matched_entities.append(name)
            
            # 方法2: 关键词分割匹配
            if not matched_entities:
                # 使用更智能的关键词提取方法
                words = query.split()
                
                # 过滤停用词
                filtered_words = [word for word in words if word not in stop_words]
                
                # 尝试组合相邻的词来匹配资源名称
                for i in range(len(filtered_words)):
                    # 单个词匹配
                    matched_entities.extend([name for name in resource_names if filtered_words[i] in name])
                    
                    # 双词组合匹配
                    if i < len(filtered_words) - 1:
                        two_word = f"{filtered_words[i]}{filtered_words[i+1]}"
                        matched_entities.extend([name for name in resource_names if two_word in name])
                    
                    # 三词组合匹配
                    if i < len(filtered_words) - 2:
                        three_word = f"{filtered_words[i]}{filtered_words[i+1]}{filtered_words[i+2]}"
                        matched_entities.extend([name for name in resource_names if three_word in name])
        
        # 去重并返回结果
        return list(set(matched_entities))
    
    def get_all_resource_details(self) -> List[Dict[str, Any]]:
        """获取所有资源详情"""
        resources = self.db.query(ResourceDetails).all()
        return [{'id': r.id, 'name': r.details_name, 'description': r.description} for r in resources]
    
    def search_resources_by_keyword(self, keyword: str) -> List[Dict[str, Any]]:
        """根据关键词搜索资源节点"""
        # 使用SQLAlchemy的like操作符进行模糊搜索
        resources = self.db.query(ResourceDetails).filter(
            ResourceDetails.details_name.like(f'%{keyword}%') | 
            ResourceDetails.description.like(f'%{keyword}%') |
            ResourceDetails.annotations.like(f'%{keyword}%')
        ).all()
        
        result = []
        for resource in resources:
            result.append({
                'id': resource.id,
                'name': resource.details_name,
                'description': resource.description,
                'category_id': resource.category_id
            })
        
        return result
    
    def search_resources_by_name(self, name: str) -> List[Dict[str, Any]]:
        """根据名称精确搜索资源"""
        resources = self.db.query(ResourceDetails).filter(ResourceDetails.details_name == name).all()
        return [{'id': r.id, 'name': r.details_name, 'description': r.description, 'category_id': r.category_id} for r in resources]
    
    def build_context_for_qa(self, query: str) -> List[str]:
        """为问答系统构建上下文文档，增强对上下游依赖查询的处理"""
        print(f"开始处理查询: {query}")
        
        # 1. 检查是否是包含关系查询
        if "包含关系" in query or ("包含" in query and "关系" in query):
            print("检测到包含关系查询")
            return self._build_containment_context()
        
        # 2. 检查是否是上下游依赖查询
        if "上游" in query or "下游" in query or "依赖" in query:
            print("检测到上下游依赖查询")
            return self._build_dependency_context(query)
        
        # 3. 使用改进的实体提取方法
        entities = self.extract_entities_from_query(query)
        print(f"从查询'{query}'中提取到实体: {entities}")
        
        all_relevant_resources = []
        
        # 4. 对每个实体进行精确搜索
        for entity in entities:
            resources = self.search_resources_by_name(entity)
            all_relevant_resources.extend(resources)
            if resources:
                print(f"通过精确搜索找到 {len(resources)} 个资源: {entity}")
        
        # 5. 如果没有找到精确匹配，使用关键词搜索
        if not all_relevant_resources:
            keywords = query.split()
            for keyword in keywords:
                # 跳过常见的停用词
                stop_words = ['什么', '如何', '为什么', '哪个', '哪里', '有没有', '是否', '关系', '有', '和', '与', '及', '以及', '或者', '还是', '上游', '下游', '依赖']
                if keyword not in stop_words:
                    resources = self.search_resources_by_keyword(keyword)
                    all_relevant_resources.extend(resources)
                    if resources:
                        print(f"通过关键词搜索找到 {len(resources)} 个资源: {keyword}")
        
        # 6. 构建上下文文档
        context_docs = []
        for resource in all_relevant_resources:
            # 获取资源本身的信息
            resource_text = f"资源名称: {resource['name']}\n描述: {resource['description']}\n"
            context_docs.append(resource_text)
            
            # 获取与该资源相关的资源
            related_resources = self.find_related_resources(resource['id'], depth=1)
            
            for related in related_resources:
                # 获取相关资源的详细信息
                related_detail = self.db.query(ResourceDetails).filter_by(id=related['id']).first()
                if related_detail:
                    related_text = f"资源名称: {related_detail.details_name}\n描述: {related_detail.description}\n与{resource['name']}的关系: {related['relationship']}\n"
                    context_docs.append(related_text)
        
        # 7. 特殊处理关系查询
        if "关系" in query or "关联" in query:
            # 提取查询中的两个实体
            entities = self.extract_entities_from_query(query)
            if len(entities) >= 2:
                # 查找两个实体之间的关系
                relationships = self.find_relationship_between_resources(entities[0], entities[1])
                if relationships:
                    relationship_text = f"实体关系信息:\n"
                    for rel in relationships:
                        relationship_text += f"{rel['from']} --({rel['relationship']})--> {rel['to']}\n"
                    
                    context_docs.append(relationship_text)
        
        print(f"最终构建了 {len(context_docs)} 个上下文文档")
        return context_docs
    
    def _build_dependency_context(self, query: str) -> List[str]:
        """构建上下游依赖查询的上下文"""
        # 提取查询中的实体
        entities = self.extract_entities_from_query(query)
        
        if not entities:
            return []
        
        # 获取第一个实体的详细信息
        entity_name = entities[0]
        resource = self.db.query(ResourceDetails).filter(ResourceDetails.details_name == entity_name).first()
        
        if not resource:
            return []
        
        context_docs = []
        
        # 判断查询类型
        if "上游" in query:
            # 获取上游依赖
            upstream_deps = self.dependency_analyzer.find_upstream_dependencies(resource.id)
            if upstream_deps:
                context_text = f"{entity_name}的上游依赖:\n"
                for dep in upstream_deps:
                    context_text += f"- {dep['name']} ({dep['relationship']})\n"
                context_docs.append(context_text)
        elif "下游" in query:
            # 获取下游依赖
            downstream_deps = self.dependency_analyzer.find_downstream_dependencies(resource.id)
            if downstream_deps:
                context_text = f"{entity_name}的下游依赖:\n"
                for dep in downstream_deps:
                    context_text += f"- {dep['name']} ({dep['relationship']})\n"
                context_docs.append(context_text)
        else:
            # 获取所有依赖
            all_deps = self.dependency_analyzer.find_all_dependencies(resource.id)
            if all_deps:
                context_text = f"{entity_name}的所有依赖关系:\n"
                for dep in all_deps:
                    direction = " <- " if dep['direction'] == 'upstream' else " -> "
                    context_text += f"{dep['related_resource']} {direction} {entity_name} ({dep['relationship']})\n"
                context_docs.append(context_text)
        
        return context_docs
    
    def _build_containment_context(self) -> List[str]:
        """构建包含关系查询的上下文"""
        # 这里应该实现包含关系查询的上下文构建逻辑
        # 暂时返回空列表，需要根据实际需求实现
        return []
    
    def find_related_resources(self, resource_id: str, depth: int = 1) -> List[Dict[str, Any]]:
        """查找与指定资源相关的其他资源（多跳查询）"""
        visited = set()
        related_resources = []
        
        def dfs(current_id: str, current_depth: int):
            if current_id in visited or current_depth > depth:
                return
            
            visited.add(current_id)
            
            # 查找从当前节点出发的关系
            outgoing_relationships = self.db.query(ResourceEntitiesMap).filter_by(start_nodes_id=current_id).all()
            for rel in outgoing_relationships:
                end_node = self.db.query(ResourceDetails).filter_by(id=rel.end_nodes_id).first()
                if end_node and end_node.id not in visited:
                    relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
                    related_resources.append({
                        'id': end_node.id,
                        'name': end_node.details_name,
                        'type': 'outgoing',
                        'relationship': relationship_def.name if relationship_def else '未知关系'
                    })
                    dfs(end_node.id, current_depth + 1)
            
            # 查找指向当前节点的关系
            incoming_relationships = self.db.query(ResourceEntitiesMap).filter_by(end_nodes_id=current_id).all()
            for rel in incoming_relationships:
                start_node = self.db.query(ResourceDetails).filter_by(id=rel.start_nodes_id).first()
                if start_node and start_node.id not in visited:
                    relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
                    related_resources.append({
                        'id': start_node.id,
                        'name': start_node.details_name,
                        'type': 'incoming',
                        'relationship': relationship_def.name if relationship_def else '未知关系'
                    })
                    dfs(start_node.id, current_depth + 1)
        
        dfs(resource_id, 0)
        return related_resources
    
    def find_relationship_between_resources(self, resource1_name: str, resource2_name: str) -> List[Dict[str, Any]]:
        """查找两个资源之间的关系"""
        # 获取资源详情
        resource1 = self.db.query(ResourceDetails).filter_by(details_name=resource1_name).first()
        resource2 = self.db.query(ResourceDetails).filter_by(details_name=resource2_name).first()
        
        if not resource1 or not resource2:
            return []
        
        relationships = []
        
        # 查找从resource1到resource2的关系
        direct_relations = self.db.query(ResourceEntitiesMap).filter_by(
            start_nodes_id=resource1.id, 
            end_nodes_id=resource2.id
        ).all()
        
        for rel in direct_relations:
            relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
            relationships.append({
                'from': resource1.details_name,
                'to': resource2.details_name,
                'relationship': relationship_def.name if relationship_def else '未知关系'
            })
        
        # 查找从resource2到resource1的关系
        reverse_relations = self.db.query(ResourceEntitiesMap).filter_by(
            start_nodes_id=resource2.id, 
            end_nodes_id=resource1.id
        ).all()
        
        for rel in reverse_relations:
            relationship_def = self.db.query(RelationshipDefinition).filter_by(id=rel.relation_id).first()
            relationships.append({
                'from': resource2.details_name,
                'to': resource1.details_name,
                'relationship': relationship_def.name if relationship_def else '未知关系'
            })
        
        return relationships